package cn.mazexal.exambg.controller.common;

import cn.mazexal.exambg.common.anno.PermitGuest;
import cn.mazexal.exambg.common.models.SingleResponse;
import cn.mazexal.exambg.controller.BaseController;
import cn.mazexal.exambg.models.enums.FileFrom;
import cn.mazexal.exambg.models.vo.other.EditorImgVO;
import cn.mazexal.exambg.models.vo.other.EditorImgVOItem;
import cn.mazexal.exambg.utils.MD5Utils;
import cn.mazexal.exambg.utils.VerifyCode;
import cn.mazexal.exambg.utils.qiniu.QiniuOssUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

/**
 * @author: Mazexal
 * Date: 2021/9/21
 */
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController extends BaseController {
    @Resource
    private QiniuOssUtil qiniuOssUtil;

    /**
     * 获取验证码图片
     *
     * @param response
     * @param request
     */
    @RequestMapping("/getVerificationCode")
    public void getVerificationCode(HttpServletResponse response, HttpServletRequest request) {
        try {
            int width = 200;
            int height = 69;
            BufferedImage verifyImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            //生成对应宽高的初始图片
            String randomText = VerifyCode.drawRandomText(width, height, verifyImg);
            //单独的一个类方法，出于代码复用考虑，进行了封装。
            //功能是生成验证码字符并加上噪点，干扰线，返回值为验证码字符
            request.getSession().setAttribute("verifyCode", randomText.toLowerCase());
            //必须设置响应内容类型为图片，否则前台不识别
            response.setContentType("image/png");
            //获取文件输出流
            OutputStream os = response.getOutputStream();
            //输出图片流
            ImageIO.write(verifyImg, "png", os);
            os.flush();
            os.close();//关闭流
        } catch (IOException e) {
            log.error(e.getMessage());
            e.printStackTrace();
        }
    }


    @PostMapping(value = "/markdownImg")
    public SingleResponse markdownImg(@RequestParam(value = "file") MultipartFile file) {
        return uploadImg(file);
    }


    @PostMapping(value = "/editorUploadImg")
    @PermitGuest
    public EditorImgVO editorUploadImg(@RequestParam(value = "file") MultipartFile[] files) throws Exception {
        EditorImgVO res = new EditorImgVO();
        List<EditorImgVOItem> items = new ArrayList<>();
        res.setErrno(0);
        for (MultipartFile file : files) {
            // 如果文件超过500K, 提示文件过大
            if (file.getSize() > 500 * 1024) {
                res = new EditorImgVO();
                res.setErrno(500);
                return res;
            }
            if (file.isEmpty()) {
                res = new EditorImgVO();
                res.setErrno(500);
                return res;
            }
            // 文件名
            String fileName = file.getOriginalFilename();
            // 后缀名
            String suffixName = fileName.substring(fileName.lastIndexOf("."));
            if (!checkSuffix(suffixName)) {
                res = new EditorImgVO();
                res.setErrno(500);
                return res;
            }
            // 新文件名
            try {
                fileName = MD5Utils.getMD5(file.getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
            String name = qiniuOssUtil.upload(file, FileFrom.EXAM);
            EditorImgVOItem item = new EditorImgVOItem();
            // 这里上传到七牛云, 所以暂时
            item.setUrl(name);
            item.setAlt(fileName);
            item.setHref("");
            items.add(item);
        }
        res.setData(items);
        return res;
    }

    private SingleResponse uploadImg(MultipartFile file) {
        SingleResponse res = SingleResponse.success();
        if (file.isEmpty()) {
            return SingleResponse.error("500", "文件为空");
        }
        Long userid = getUserId();
        // 文件名
        String fileName = file.getOriginalFilename();
        // 后缀名
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        if (!checkSuffix(suffixName)) {
            return SingleResponse.error("500", "图片格式不支持");
        }
        // 上传后的路径
        String filePath = "/opt/tarotImage/" + userid + "/";
        String os = System.getProperty("os.name");
        if (os.toLowerCase().startsWith("win")) {
            filePath = "D://tarotImage//" + userid + "/";
        }
        // 新文件名
        try {
            fileName = MD5Utils.getMD5(file.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        File dest = new File(filePath + fileName + suffixName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        String fileFullName = "/tarotImage/" + userid + "/" + fileName + suffixName;
        res.setData(fileFullName);
        return res;
    }

    private boolean checkSuffix(String imgPath) {
        Boolean flag = false;
        //图片格式
        String[] FILETYPES = new String[]{
                ".jpg", ".bmp", ".jpeg", ".png", ".gif",
                ".JPG", ".BMP", ".JPEG", ".PNG", ".GIF"
        };
        if (!StringUtils.isBlank(imgPath)) {
            for (int i = 0; i < FILETYPES.length; i++) {
                String fileType = FILETYPES[i];
                if (imgPath.endsWith(fileType)) {
                    flag = true;
                    break;
                }
            }
        }
        return flag;
    }

}
